from itertools import takewhile
from random import random

class Player:
    def __init__(self):
        self.start_players = 0
        self.start_food = 0

    def hunt_outcomes(self, food_earnings):
        pass

    def round_end(self, award, m, number_hunters):
        pass

    def hunt_choices(self, round_number, current_food, current_reputation, m, player_reputations):
        N = len(player_reputations)

        if self.start_players == 0:
            self.start_players = N
            self.start_food = current_food

            # Startup strategy: Secure the reputation early on
            from random import choice
            return [choice('hss') for _ in player_reputations]

        if N <= 2:
            return ['s']

        # sort players by eagernes to hunt
        players = sorted(zip(player_reputations, range(N)), reverse=True)
        players_assessed = 0

        #calculate histogram of player ratings
        hist = {}
        for i in player_reputations:
            hist[i] = hist[i] + 1 if i in hist else 1
        hist = sorted(hist.items(), key=lambda _: _[1], reverse=True)

        # calculate various statistics
        # not necessarily used anywhere in the code
        avg_rating = sum(player_reputations) / float(N)
        min_rating = min(player_reputations)
        max_rating = max(player_reputations)
        med_rating = (hist[len(hist) // 2][0] + hist[(len(hist) + 1) // 2][0]) / 2.0
        hunter_pool = [i for i in takewhile(lambda x: x[0] > max_rating / 3.0, hist)]
        min_hunter = min(hunter_pool) if hunter_pool else min_rating

        # prepare moves
        moves = ['s' for _ in range(N)]
        hunts = 0

        food_ratio = self.start_food / float(self.start_food + current_food)
        players_ratio = self.start_players / float(self.start_players + N)

        # set various thresholds based on histogram
        potential_hunters = sum(i[1] for i in hunter_pool)
        hunts_threshold = 1.20 * potential_hunters * food_ratio
        slacker_threshold = (1.0 - med_rating) * players_ratio

        # decision loop
        for players_assessed, player in enumerate(players):
            criteria = (
                # check if we are in the safe area
                max_rating >= player[0] >= min_hunter,
                # check if we are not against slackers
                player[0] > slacker_threshold,
                # check if we still have hunting reserves
                hunts < hunts_threshold,
                # skip several hunters to feed off
                #(players_assessed < (potential_hunters - hunts_threshold)) or
                #    not (food_ratio > 0.20 and random() > .4),
                random() > .3,
                player[0] < .7
                )
            if  all(criteria):
                hunts += 1
                moves[player[1]] = 'h'

        return moves
